#include<iostream>
#include<queue>
#include<pthread.h>

using namespace std;

const int defaultcap=5;

template<class T>
class BlockQueue
{
    public:
        BlockQueue(int cap=defaultcap):_capacity(cap)
        {
            pthread_mutex_init(&_mutex,nullptr);
            pthread_cond_init(&_p_cond,nullptr);
            pthread_cond_init(&_c_cond,nullptr);
        }

        void Push(const T& in)
        {
            pthread_mutex_lock(&_mutex);
            while(IsFull())
            {
                //阻塞等待
                pthread_cond_wait(&_p_cond,&_mutex);
            }
            _q.push(in);

            //唤醒消费者
            pthread_cond_signal(&_c_cond);
            pthread_mutex_unlock(&_mutex);
        }
        bool IsFull()
        {
            return  _q.size()==_capacity;
        }
        void Pop( T* out)
        {
            pthread_mutex_lock(&_mutex);
            while(IsEmpty())
            {
                //阻塞等待
                pthread_cond_wait(&_c_cond,&_mutex);
            }
            *out=_q.front();
            _q.pop();

            //唤醒生产者
            pthread_cond_signal(&_p_cond);
            pthread_mutex_unlock(&_mutex);
        }
        
        bool IsEmpty()
        {
            return _q.size()==0;
        }

        ~ BlockQueue()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_p_cond);
            pthread_cond_destroy(&_c_cond);
        }
    private:
        queue<T> _q;
        int _capacity;//_q.size()==_capacity，满了不能生产，_q.size()==0，空了，不能再消费
        pthread_mutex_t _mutex;
        pthread_cond_t _p_cond;//给生产者
        pthread_cond_t _c_cond;//给消费者
};